#include "thread_pool.hpp"
#include <iostream>
#include <chrono>


TaskQueue::TaskQueue(size_t capacity) 
    : m_capacity(capacity)
    , m_isClosed(false) {
    
    if (m_capacity == 0) {
        throw std::invalid_argument("任务队列大小不能为0");
    }    
}

TaskQueue::~TaskQueue() {
    // 先关闭队列
    close();

    std::queue<ElemType> empty_queue;
    m_taskQueue.swap(empty_queue);
}

void TaskQueue::push(ElemType pTask) {
    std::unique_lock<std::mutex> lock(m_mutex);

    while(!m_isClosed && m_taskQueue.size() == m_capacity) {
        m_notFull.wait(lock);
    }

    // 如果队列已关闭，暂停唤醒和添加任务
    if (m_isClosed) {
        throw std::runtime_error("无法添加任务，任务队列已关闭");
    }

    // 添加任务
    m_taskQueue.push(std::move(pTask));

    // 唤醒线程
    m_notEmpty.notify_one();
}


TaskQueue::ElemType TaskQueue::pop() {
    std::unique_lock<std::mutex> lock(m_mutex);

    while (!m_isClosed && m_taskQueue.empty()) {
        m_notEmpty.wait(lock);
    }

    // 如果队列关闭且队列为空，安全退出
    if (m_isClosed && m_taskQueue.empty()) {
        return nullptr;
    }

    ElemType task = std::move(m_taskQueue.front());
    m_taskQueue.pop();

    m_notFull.notify_one();

    return task;
}


bool TaskQueue::full() const {
    std::lock_guard<std::mutex> lock(m_mutex);
    return  m_taskQueue.size() == m_capacity;
}   


bool TaskQueue::empty() const {
    std::lock_guard<std::mutex> lock(m_mutex);
    return m_taskQueue.empty();
}

void TaskQueue::open() {
    std::unique_lock<std::mutex> lock(m_mutex);
    m_isClosed = false;
}

void TaskQueue::close() {
    std::unique_lock<std::mutex> lock(m_mutex);
    m_isClosed = true; 
    // 唤醒所有等待的消费者和生产者，使之检查m_isClosed标志并退出 
    m_notEmpty.notify_all();
    m_notFull.notify_all();
    
}

size_t TaskQueue::get_waiting_tasks_count() const {
    std::lock_guard<std::mutex> lock(m_mutex);
    return m_taskQueue.size();
}


ThreadPool::ThreadPool(size_t threadNum, size_t queueSize) 
    : m_threadNum(threadNum)
    , m_taskQueue(queueSize)
{
    if (m_threadNum == 0) {
        throw std::invalid_argument("线程池至少需要一个线程");
    }    
}

ThreadPool::~ThreadPool() {
    stop();
}

void ThreadPool::start() {
    std::unique_lock<std::mutex> lock(m_stateMutex);
    if (!m_threads.empty()) {
        return; 
    }

    m_isExit = false;
    m_taskQueue.open();


    for (size_t i = 0; i < m_threadNum; ++i) {
        m_threads.emplace_back(&ThreadPool::woker_loop, this);
    }    
}

void ThreadPool::woker_loop() {
    while (true) {
        std::unique_ptr<Task> pTask = m_taskQueue.pop();

        if (pTask == nullptr) {
            break;
        }
        // 执行任务
        try {
            //pTask->process();
            (*pTask)();
        }
        catch (const std::exception& e) {
            std::cerr << "Task throw an exception" << e.what() << std::endl;
        } 
        catch (...) {
            std::cerr << "Task throw an unknown exception" << std::endl;
        }
    }
}


void ThreadPool::addTask(std::unique_ptr<Task> pTask) {
    if (!pTask) {
        throw std::invalid_argument("Cannot add null task.");
    }
    std::lock_guard<std::mutex> lock(m_stateMutex); // 保护 m_isExit
    if (m_isExit) {
        throw std::runtime_error("Cannot add task: ThreadPool is shutting down.");
    }
    // 将任务添加到队列，push 会处理队列满时的等待或抛异常
    m_taskQueue.push(std::move(pTask)); 
}


void ThreadPool::stop() {
    std::unique_lock<std::mutex> lock(m_stateMutex);
    if (m_isExit) {
        return; 
    }

    m_isExit = true;
    m_taskQueue.close();

    for (std::thread& worker : m_threads) {
        if (worker.joinable()) {
            worker.join();
        }
    }
    m_threads.clear();
}

void ThreadPool::shutdown_immediate() {
    std::unique_lock<std::mutex> lock(m_stateMutex);
    if (m_isExit) {
        return;  
    }
    m_isExit = true;

    m_taskQueue.close();

    std::queue<TaskQueue::ElemType> empty_queue;
    m_taskQueue.m_taskQueue.swap(empty_queue);

    for (std::thread& worker : m_threads) {
        if (worker.joinable()) {
            worker.join();
        }
    } 

    m_threads.clear();
}



